package com.qipa.netty.handler;


import com.alibaba.fastjson.JSONObject;
import com.qipa.netty.heartbeat.WebSocketChannelMap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.util.concurrent.ImmediateEventExecutor;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Component
public class TextWebSocketFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    Logger logger = Logger.getLogger(TextWebSocketFrameHandler.class);

    private final ChannelGroup group;

    public TextWebSocketFrameHandler(ChannelGroup group) {
        this.group = group;
    }

    public TextWebSocketFrameHandler() {
        this.group = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE);
    }

    public ChannelGroup getGroup() {
        return group;
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        //当WebSocket连接成功
        if (evt == WebSocketServerProtocolHandler.ServerHandshakeStateEvent.HANDSHAKE_COMPLETE) {
            //不需要再处理HTTP请求
            ctx.pipeline().remove(HealthServerHandler.class);
            //告诉已经连接的客户端有新的客户端连接进来了
//            group.writeAndFlush(new TextWebSocketFrame("Client " + ctx.channel() + " joined"));
            //将新的客户端添加到ChannelGroup中
            group.add(ctx.channel());

            //手动保存websocket连接到map
            Channel channel = ctx.channel();
            WebSocketChannelMap.add("gameAll", channel);
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }

    /**
     * 心跳推送也是这里
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        TextWebSocketFrame retain = msg.retain();
        String text = retain.text();
        logger.info("socket推送内容："+text);
        //消息转发给每一个客户端
//        group.writeAndFlush(msg.retain());
        group.writeAndFlush(new TextWebSocketFrame("ping"));

        JSONObject jsonObject = JSONObject.parseObject(text);
        String type = jsonObject.getString("type");
        if(type.startsWith("gameId_")){
            String[] split = type.split("_");
            String gameId = split[1];
            //把当前连接保存到某个游戏的连接中
            Channel channel = ctx.channel();
            Map<String, List<Channel>> channels = WebSocketChannelMap.getChannels();
            List<Channel> gameAllchannels = channels.get("gameAll");
            logger.info("连接全部游戏的长连接数量："+gameAllchannels.size());
            List<Channel> channelsNew = new ArrayList<>();
            for(Channel channel1: gameAllchannels){
                if(!channel1.id().asLongText().equals(channel.id().asLongText())){
                    channelsNew.add(channel1);
                }else{
                    logger.info("移动了某个连接到指定游戏");
                }
            }
            channels.put("gameAll", channelsNew);
            logger.info("连接全部游戏的长连接数量："+channelsNew.size());

            List<Channel> gameIdChannels = channels.get(gameId);
            if (gameIdChannels == null) {
                logger.info("添加指定游戏长连接");
                gameIdChannels = new ArrayList<>();
                gameIdChannels.add(channel);
                channels.put(gameId, gameIdChannels);
            }else{
                logger.info("连接"+gameId+"游戏的长连接数量："+gameIdChannels.size());
                gameIdChannels.add(channel);
            }
            gameIdChannels = channels.get(gameId);
            logger.info("添加成功，连接"+gameId+"游戏的长连接数量："+gameIdChannels.size());
        }
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        ctx.fireChannelUnregistered();
    }





}